/*
 * Here it will be the Copyright 
 */
package gui;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;

import kernel.OpenCVProcesor;
/**
 * Main entry point for the application
 * @author juanibarral
 *
 */
public class MainFrame extends JFrame implements ActionListener, KeyListener{

	/**
	 * Serial version for serialization
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * Instance for the singleton
	 */
	private static MainFrame instance;
	/**
	 * Menu bar
	 */
	private JMenuBar menuBar;
	/**
	 * Action Commands
	 */
	private static final String ACTION_CLOSE = "ACTION_CLOSE";
	private static final String ACTION_OPEN_FILE = "ACTION_OPEN_FILE";
	private static final String ACTION_SAVE_FILE = "ACTION_SAVE_FILE";
	private static final String ACTION_ABOUT = "ACTION_ABOUT";
	private static final String ACTION_TREATMENTS = "ACTION_TREATMENTS";
	
	/**
	 * File Menu and its items
	 */
	private JMenu menuFile;
	private JMenuItem menuFileOpenFile;
	private JMenuItem menuFileSaveFile;
	private JMenuItem menuFileClose;
	
	/**
	 * Treatment Menu and its items
	 */
	private JMenu menuTreatment;
	private JMenuItem menuTreatmentFace;
	
	/**
	 * Help Menu and its items
	 */
	private JMenu menuHelp;
	private JMenuItem menuHelpAbout;
	
	/**
	 * Panels
	 */
	private PanelBefore panelBefore;
	private PanelAfter panelAfter;
	/**
	 * Engine
	 */
	private OpenCVProcesor openCVProcesor;
	/**
	 * Others
	 */
	private boolean imageLoaded = false;
	/**
	 * Constructor
	 */
	private MainFrame()
	{
		openCVProcesor = OpenCVProcesor.getInstance();
		panelBefore = new PanelBefore();
		panelAfter = new PanelAfter();
		init();
	}
	/**
	 * Frame initialization
	 */
	private void init()
	{
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//		this.setExtendedState(MAXIMIZED_BOTH);	
		this.setSize(800,800);
		this.setTitle("Dermasoft v. 0.1");
		this.setLayout(new GridLayout(1, 2));
		this.addKeyListener(this);
		
		menuBar = new JMenuBar();
		/*
		 * File Menu
		 */
		menuFile = new JMenu("File");
		
		menuFileOpenFile = new JMenuItem("Open File...");
		menuFileOpenFile.addActionListener(this);
		menuFileOpenFile.setActionCommand(ACTION_OPEN_FILE);
		menuFile.add(menuFileOpenFile);
		
		menuFileSaveFile = new JMenuItem("Save File...");
		menuFileSaveFile.addActionListener(this);
		menuFileSaveFile.setActionCommand(ACTION_SAVE_FILE);
		menuFileSaveFile.setEnabled(false);
		menuFile.add(menuFileSaveFile);
		
		menuFile.add(new JSeparator());
		
		menuFileClose = new JMenuItem("Close");
		menuFileClose.addActionListener(this);
		menuFileClose.setActionCommand(ACTION_CLOSE);
		menuFile.add(menuFileClose);
		
		/*
		 * Treatment menu
		 */
		
		menuTreatment = new JMenu("Treatment");
		menuTreatmentFace = new JMenuItem("Face...");
		menuTreatmentFace.addActionListener(this);
		menuTreatmentFace.setActionCommand(ACTION_TREATMENTS);
		menuTreatment.add(menuTreatmentFace);
		menuTreatment.setEnabled(false);
		/*
		 * About Menu
		 */
		menuHelp = new JMenu("Help");
		menuHelpAbout = new JMenuItem("About");
		menuHelpAbout.addActionListener(this);
		menuHelpAbout.setActionCommand(ACTION_ABOUT);
		menuHelp.add(menuHelpAbout);
		
		menuBar.add(menuFile);
		menuBar.add(menuTreatment);
		menuBar.add(menuHelp);
		
		
		this.setJMenuBar(menuBar);
		this.add(panelBefore);
		this.add(panelAfter);

	}
	/**
	 * @return the instance of the singleton
	 */
	public static MainFrame getInstance()
	{
		if(instance == null)
		{
			instance = new MainFrame();
		}
		return instance;
	}

	/**
	 * Main entry point
	 * @param args
	 */
	public static void main(String[] args)
	{
		MainFrame instance = MainFrame.getInstance();
		instance.setVisible(true);
	}

	public void processImage(int maskSize) throws Exception
	{
		eraseAllAuxiliarFiles();
		double before = System.currentTimeMillis();
		String processed = openCVProcesor.smooth(panelBefore.getImageFilepath(), panelBefore.getOutputImageFilepath(), maskSize);
		double elapsed = System.currentTimeMillis() - before;
		panelAfter.updateImage( panelBefore.getOutputImageFilepath());
		JOptionPane.showMessageDialog(this, "Elapsed time: " + elapsed + " milliseconds\n" + processed);
	}
	
	public void processImageWithBuffers(int maskSize)
	{
		double before = System.currentTimeMillis();
		BufferedImage input = panelBefore.getBufferedImage();
		BufferedImage output = new BufferedImage(input.getWidth(), input.getHeight(), input.getType());
		openCVProcesor.smooth(panelBefore.getImageFilepath(), output, maskSize);
		double elapsed = System.currentTimeMillis() - before;
		panelAfter.updateImage(output);
		JOptionPane.showMessageDialog(this, "Elapsed time: " + elapsed + " milliseconds");
	}
	
	@Override
	public void actionPerformed(ActionEvent event) {
		String actionCommand = event.getActionCommand();
		
		if(actionCommand.equals(ACTION_CLOSE))
		{
			try {
				eraseAllAuxiliarFiles();
			} catch (Exception e) {
				e.printStackTrace();
				JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
			}
			System.exit(0);
		}
		else if(actionCommand.equals(ACTION_OPEN_FILE))
		{
			JFileChooser fileChooser = new JFileChooser("."+File.separatorChar+"Files");
			fileChooser.addChoosableFileFilter(new utils.ImageFilter());
			int returnValue = fileChooser.showOpenDialog(this);
			if(returnValue == JFileChooser.APPROVE_OPTION)
			{
				File file = fileChooser.getSelectedFile();
				panelBefore.setImage(file.getAbsolutePath());
				panelAfter.clearImage();
				imageLoaded = true;
				menuTreatment.setEnabled(true);
				try {
					eraseAllAuxiliarFiles();
				} catch (Exception e) {
					e.printStackTrace();
					JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		}
		else if(actionCommand.equals(ACTION_TREATMENTS))
		{
			FrameTreatmentOptions treatmentFrame = new FrameTreatmentOptions(this);
			treatmentFrame.setVisible(true);
		}
		else if(actionCommand.equals(ACTION_ABOUT))
		{
			this.setEnabled(false);
			FrameAbout aboutFrame = new FrameAbout(instance);
			aboutFrame.setVisible(true);
		}	
	}
	
	private void eraseAllAuxiliarFiles()throws Exception
	{
		String dir = "."+File.separatorChar+"Files";
		File directory = new File(dir);
		String[] childs = directory.list();
		for(String s : childs)
		{
			if(s.charAt(0) == '~')
			{
				File f = new File(dir + File.separatorChar + s);
//				Make sure the file or directory exists and isn't write protected
				if (!f.exists())
					throw new IllegalArgumentException(
							"Delete: no such file or directory: " + s);

				if (!f.canWrite())
					throw new IllegalArgumentException("Delete: write protected: "
							+ s);

				// If it is a directory, make sure it is empty
				if (f.isDirectory()) {
					String[] files = f.list();
					if (files.length > 0)
						throw new IllegalArgumentException(
								"Delete: directory not empty: " + s);
				}

				// Attempt to delete it
				boolean success = f.delete();

				if (!success)
					throw new IllegalArgumentException("Delete: deletion failed");
			}
		}

	}
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
	 */
	@Override
	public void keyPressed(KeyEvent e) {
		switch(e.getKeyCode())
		{
		case KeyEvent.VK_SPACE:
			FullScreenDialog instance = new FullScreenDialog(this);
			instance.setVisible(true);
			break;
		}
	}
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
	 */
	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */
	@Override
	public void keyTyped(KeyEvent e) {
	}
}
